<html>
<head><meta charset="utf-8"><title>Tree diff rewrite tests · t-compiler/rust-analyzer · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/index.html">t-compiler/rust-analyzer</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html">Tree diff rewrite tests</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="214161097"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214161097" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214161097">(Oct 22 2020 at 09:12)</a>:</h4>
<p>Quick question regarding how I should model the unit tests. I was thinking of something like the following. <span class="user-mention" data-user-id="133169">@matklad</span> </p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[cfg(test)]</span><span class="w"></span>
<span class="k">mod</span> <span class="nn">tests</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">expect_test</span>::<span class="p">{</span><span class="n">expect</span><span class="p">,</span><span class="w"> </span><span class="n">Expect</span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">text_edit</span>::<span class="n">TextEdit</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="k">crate</span>::<span class="n">AstNode</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">test_diff</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>
<span class="s">use text_edit::TextEdit;</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                TreeDiff {</span>
<span class="s">                    replacements: {</span>
<span class="s">                        Token(</span>
<span class="s">                            WHITESPACE@35..37 "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">",</span>
<span class="s">                        ): Token(</span>
<span class="s">                            WHITESPACE@35..36 "</span><span class="err">\</span><span class="n">n</span><span class="s">",</span>
<span class="s">                        ),</span>
<span class="s">                        Token(</span>
<span class="s">                            CRATE_KW@41..46 "</span><span class="k">crate</span><span class="s">",</span>
<span class="s">                        ): Node(</span>
<span class="s">                            NAME_REF@40..49</span>
<span class="s">                              IDENT@40..49 "</span><span class="n">text_edit</span><span class="s">"</span>
<span class="s">                            ,</span>
<span class="s">                        ),</span>
<span class="s">                        Token(</span>
<span class="s">                            IDENT@48..55 "</span><span class="n">AstNode</span><span class="s">",</span>
<span class="s">                        ): Token(</span>
<span class="s">                            IDENT@51..59 "</span><span class="n">TextEdit</span><span class="s">",</span>
<span class="s">                        ),</span>
<span class="s">                        Token(</span>
<span class="s">                            WHITESPACE@56..57 "</span><span class="err">\</span><span class="n">n</span><span class="s">",</span>
<span class="s">                        ): Token(</span>
<span class="s">                            WHITESPACE@60..62 "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">",</span>
<span class="s">                        ),</span>
<span class="s">                    },</span>
<span class="s">                    deletions: [],</span>
<span class="s">                    insertions: {</span>
<span class="s">                        Token(</span>
<span class="s">                            WHITESPACE@56..57 "</span><span class="err">\</span><span class="n">n</span><span class="s">",</span>
<span class="s">                        ): [</span>
<span class="s">                            Node(</span>
<span class="s">                                USE@62..81</span>
<span class="s">                                  USE_KW@62..65 "</span><span class="k">use</span><span class="s">"</span>
<span class="s">                                  WHITESPACE@65..66 "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                                  USE_TREE@66..80</span>
<span class="s">                                    PATH@66..80</span>
<span class="s">                                      PATH@66..71</span>
<span class="s">                                        PATH_SEGMENT@66..71</span>
<span class="s">                                          CRATE_KW@66..71 "</span><span class="k">crate</span><span class="s">"</span>
<span class="s">                                      COLON2@71..73 "</span>::<span class="s">"</span>
<span class="s">                                      PATH_SEGMENT@73..80</span>
<span class="s">                                        NAME_REF@73..80</span>
<span class="s">                                          IDENT@73..80 "</span><span class="n">AstNode</span><span class="s">"</span>
<span class="s">                                  SEMICOLON@80..81 "</span><span class="p">;</span><span class="s">"</span>
<span class="s">                                ,</span>
<span class="s">                            ),</span>
<span class="s">                            Token(</span>
<span class="s">                                WHITESPACE@81..82 "</span><span class="err">\</span><span class="n">n</span><span class="s">",</span>
<span class="s">                            ),</span>
<span class="s">                        ],</span>
<span class="s">                    },</span>
<span class="s">                }"</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">fn</span> <span class="nf">check_diff</span><span class="p">(</span><span class="n">from</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">,</span><span class="w"> </span><span class="n">to</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">,</span><span class="w"> </span><span class="n">expected_diff</span>: <span class="nc">Expect</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">from_node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">crate</span>::<span class="n">SourceFile</span>::<span class="n">parse</span><span class="p">(</span><span class="n">from</span><span class="p">).</span><span class="n">tree</span><span class="p">().</span><span class="n">syntax</span><span class="p">().</span><span class="n">clone</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">to_node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">crate</span>::<span class="n">SourceFile</span>::<span class="n">parse</span><span class="p">(</span><span class="n">to</span><span class="p">).</span><span class="n">tree</span><span class="p">().</span><span class="n">syntax</span><span class="p">().</span><span class="n">clone</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">diff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">super</span>::<span class="n">diff</span><span class="p">(</span><span class="o">&amp;</span><span class="n">from_node</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">to_node</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">expected_diff</span><span class="p">.</span><span class="n">assert_eq</span><span class="p">(</span><span class="o">&amp;</span><span class="n">format</span><span class="o">!</span><span class="p">(</span><span class="s">"{:#?}"</span><span class="p">,</span><span class="w"> </span><span class="n">diff</span><span class="p">));</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">from</span><span class="p">.</span><span class="n">to_owned</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">text_edit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">TextEdit</span>::<span class="n">builder</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="n">diff</span><span class="p">.</span><span class="n">into_text_edit</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">text_edit</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">text_edit</span><span class="p">.</span><span class="n">finish</span><span class="p">().</span><span class="n">apply</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">from</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="o">&amp;*</span><span class="n">from</span><span class="p">,</span><span class="w"> </span><span class="n">to</span><span class="p">,</span><span class="w"> </span><span class="s">"diff did not turn `from` to `to`"</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="214161271"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214161271" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214161271">(Oct 22 2020 at 09:14)</a>:</h4>
<p>Though i guess this gets rather unwieldy quite fast? not sure</p>



<a name="214162879"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214162879" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214162879">(Oct 22 2020 at 09:31)</a>:</h4>
<p>I'd use something more visual</p>



<a name="214162961"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214162961" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214162961">(Oct 22 2020 at 09:32)</a>:</h4>
<p>Specifically, when rendering insertions and deletions, I'd use Display of nodes, rather than verbose debug</p>



<a name="214163078"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214163078" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214163078">(Oct 22 2020 at 09:33)</a>:</h4>
<p>I imgine something like this would work</p>
<div class="codehilite"><pre><span></span><code>replacements:

STRUCT_DEF@10..20 -&gt;
&quot;enum Foo { }&quot;

...
</code></pre></div>



<a name="214163101"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214163101" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214163101">(Oct 22 2020 at 09:33)</a>:</h4>
<p>Ie, we use <code>{:?}</code> for anchor and <code>{}</code> for replacement</p>



<a name="214166455"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214166455" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214166455">(Oct 22 2020 at 10:10)</a>:</h4>
<p>So something like this?</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[cfg(test)]</span><span class="w"></span>
<span class="k">mod</span> <span class="nn">tests</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">expect_test</span>::<span class="p">{</span><span class="n">expect</span><span class="p">,</span><span class="w"> </span><span class="n">Expect</span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">itertools</span>::<span class="n">Itertools</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">text_edit</span>::<span class="n">TextEdit</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="k">crate</span>::<span class="n">AstNode</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">insert_use</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>
<span class="s">use text_edit::TextEdit;</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insetions:</span>

<span class="s">                Token(WHITESPACE@56..57 "</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="k">use</span><span class="w"> </span><span class="k">crate</span>::<span class="n">AstNode</span><span class="p">;</span><span class="s">"</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>

<span class="s">                replacements:</span>

<span class="s">                Token(WHITESPACE@35..37 "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>
<span class="s">                Token(CRATE_KW@41..46 "</span><span class="k">crate</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="n">text_edit</span><span class="s">"</span>
<span class="s">                Token(IDENT@48..55 "</span><span class="n">AstNode</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="n">TextEdit</span><span class="s">"</span>
<span class="s">                Token(WHITESPACE@56..57 "</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="w"></span>

<span class="w">                </span><span class="s">"</span>

<span class="s">                deletions:</span>


<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">remove_use</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>
<span class="s">use text_edit::TextEdit;</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insetions:</span>



<span class="s">                replacements:</span>

<span class="s">                Node(NAME_REF@40..49) -&gt;</span>
<span class="s">                "</span><span class="k">crate</span><span class="s">"</span>
<span class="s">                Token(IDENT@51..59 "</span><span class="n">TextEdit</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="n">AstNode</span><span class="s">"</span>
<span class="s">                Token(WHITESPACE@60..62 "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>
<span class="s">                Token(WHITESPACE@35..36 "</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="w"></span>

<span class="w">                </span><span class="s">"</span>

<span class="s">                deletions:</span>

<span class="s">                "</span><span class="k">use</span><span class="w"> </span><span class="k">crate</span>::<span class="n">AstNode</span><span class="p">;</span><span class="s">"</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>
<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">merge_use</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="s">"</span>
<span class="s">use std::{</span>
<span class="s">    fmt,</span>
<span class="s">    hash::BuildHasherDefault,</span>
<span class="s">    ops::{self, RangeInclusive},</span>
<span class="s">};</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="s">"</span>
<span class="s">use std::fmt;</span>
<span class="s">use std::hash::BuildHasherDefault;</span>
<span class="s">use std::ops::{self, RangeInclusive};</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insetions:</span>

<span class="s">                Node(PATH_SEGMENT@5..8) -&gt;</span>
<span class="s">                "</span>::<span class="s">"</span>
<span class="s">                "</span><span class="n">fmt</span><span class="s">"</span>
<span class="s">                Token(WHITESPACE@86..99 "</span><span class="w">            </span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">hash</span>::<span class="n">BuildHasherDefault</span><span class="p">;</span><span class="s">"</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>
<span class="s">                "</span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">ops</span>::<span class="p">{</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">RangeInclusive</span><span class="p">};</span><span class="s">"</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>

<span class="s">                replacements:</span>

<span class="s">                Token(WHITESPACE@86..99 "</span><span class="w">            </span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>
<span class="s">                Token(IDENT@5..8 "</span><span class="n">std</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="n">std</span><span class="s">"</span>

<span class="s">                deletions:</span>

<span class="s">                "</span>::<span class="s">"</span>
<span class="s">                "</span><span class="p">{</span><span class="w"></span>
<span class="w">                    </span><span class="n">fmt</span><span class="p">,</span><span class="w"></span>
<span class="w">                    </span><span class="n">hash</span>::<span class="n">BuildHasherDefault</span><span class="p">,</span><span class="w"></span>
<span class="w">                    </span><span class="n">ops</span>::<span class="p">{</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">RangeInclusive</span><span class="p">},</span><span class="w"></span>
<span class="w">                </span><span class="p">}</span><span class="s">"</span>
<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">dd</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">fn main() {</span>
<span class="s">    if&lt;|&gt; let Ok(x) = Err(92) {</span>
<span class="s">        foo(x);</span>
<span class="s">    }</span>
<span class="s">}</span>
<span class="s">            "</span><span class="err">#</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">fn main() {</span>
<span class="s">    let x = match Err(92) {</span>
<span class="s">        Ok(it) =&gt; it,</span>
<span class="s">        _ =&gt; return,</span>
<span class="s">    };</span>
<span class="s">    foo(x);</span>
<span class="s">}</span>
<span class="s">            "</span><span class="err">#</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insetions:</span>

<span class="s">                Node(IF_EXPR@17..22) -&gt;</span>
<span class="s">                "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                "</span><span class="n">x</span><span class="s">"</span>
<span class="s">                "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                "</span><span class="o">=</span><span class="s">"</span>
<span class="s">                "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                "</span><span class="k">match</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="mi">92</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">it</span><span class="p">,</span><span class="w"></span>
<span class="w">                        </span><span class="n">_</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">return</span><span class="p">,</span><span class="w"></span>
<span class="w">                    </span><span class="p">}</span><span class="s">"</span>
<span class="s">                "</span><span class="p">;</span><span class="s">"</span>

<span class="s">                replacements:</span>

<span class="s">                Token(WHITESPACE@42..43 "</span><span class="w"> </span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>
<span class="s">                Node(BLOCK_EXPR@43..66) -&gt;</span>
<span class="s">                "</span><span class="p">}</span><span class="s">"</span>
<span class="s">                Token(LET_KW@23..26 "</span><span class="kd">let</span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="n">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="s">"</span>
<span class="s">                Token(WHITESPACE@26..27 "</span><span class="w"> </span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="p">;</span><span class="s">"</span>
<span class="s">                Node(IF_EXPR@17..22) -&gt;</span>
<span class="s">                "</span><span class="kd">let</span><span class="s">"</span>
<span class="s">                Token(WHITESPACE@22..23 "</span><span class="w"> </span><span class="s">") -&gt;</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                    </span><span class="s">"</span>

<span class="s">                deletions:</span>

<span class="s">                "</span><span class="nb">Ok</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="s">"</span>
<span class="s">                "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                "</span><span class="o">=</span><span class="s">"</span>
<span class="s">                "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                "</span><span class="nb">Err</span><span class="p">(</span><span class="mi">92</span><span class="p">)</span><span class="s">"</span>
<span class="s">                "</span><span class="w"></span>
<span class="w">                </span><span class="s">"</span>
<span class="s">                "</span><span class="p">}</span><span class="s">"</span>
<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">fn</span> <span class="nf">check_diff</span><span class="p">(</span><span class="n">from</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">,</span><span class="w"> </span><span class="n">to</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">,</span><span class="w"> </span><span class="n">expected_diff</span>: <span class="nc">Expect</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">from_node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">crate</span>::<span class="n">SourceFile</span>::<span class="n">parse</span><span class="p">(</span><span class="n">from</span><span class="p">).</span><span class="n">tree</span><span class="p">().</span><span class="n">syntax</span><span class="p">().</span><span class="n">clone</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">to_node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">crate</span>::<span class="n">SourceFile</span>::<span class="n">parse</span><span class="p">(</span><span class="n">to</span><span class="p">).</span><span class="n">tree</span><span class="p">().</span><span class="n">syntax</span><span class="p">().</span><span class="n">clone</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">diff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">super</span>::<span class="n">diff</span><span class="p">(</span><span class="o">&amp;</span><span class="n">from_node</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">to_node</span><span class="p">);</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">insertions</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">diff</span><span class="p">.</span><span class="n">insertions</span><span class="p">.</span><span class="n">iter</span><span class="p">().</span><span class="n">format_with</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">),</span><span class="w"> </span><span class="n">f</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">f</span><span class="p">(</span><span class="o">&amp;</span><span class="n">format</span><span class="o">!</span><span class="p">(</span><span class="w"></span>
<span class="w">                </span><span class="s">"{:?} -&gt;</span><span class="se">\n</span><span class="s">{}"</span><span class="p">,</span><span class="w"></span>
<span class="w">                </span><span class="n">k</span><span class="p">,</span><span class="w"></span>
<span class="w">                </span><span class="n">v</span><span class="p">.</span><span class="n">iter</span><span class="p">().</span><span class="n">format_with</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">v</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="o">|</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="o">&amp;</span><span class="n">format</span><span class="o">!</span><span class="p">(</span><span class="s">"</span><span class="se">\"</span><span class="s">{}</span><span class="se">\"</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)))</span><span class="w"></span>
<span class="w">            </span><span class="p">))</span><span class="w"></span>
<span class="w">        </span><span class="p">});</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">replacements</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">diff</span><span class="w"></span>
<span class="w">            </span><span class="p">.</span><span class="n">replacements</span><span class="w"></span>
<span class="w">            </span><span class="p">.</span><span class="n">iter</span><span class="p">()</span><span class="w"></span>
<span class="w">            </span><span class="p">.</span><span class="n">format_with</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">),</span><span class="w"> </span><span class="n">f</span><span class="o">|</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="o">&amp;</span><span class="n">format</span><span class="o">!</span><span class="p">(</span><span class="s">"{:?} -&gt;</span><span class="se">\n\"</span><span class="s">{}</span><span class="se">\"</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)));</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">deletions</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">diff</span><span class="p">.</span><span class="n">deletions</span><span class="p">.</span><span class="n">iter</span><span class="p">().</span><span class="n">format_with</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="o">|</span><span class="n">v</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="o">|</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="o">&amp;</span><span class="n">format</span><span class="o">!</span><span class="p">(</span><span class="s">"</span><span class="se">\"</span><span class="s">{}</span><span class="se">\"</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)));</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">actual</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">format</span><span class="o">!</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="s">"insetions:</span><span class="se">\n\n</span><span class="s">{}</span><span class="se">\n\n</span><span class="s">replacements:</span><span class="se">\n\n</span><span class="s">{}</span><span class="se">\n\n</span><span class="s">deletions:</span><span class="se">\n\n</span><span class="s">{}</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">insertions</span><span class="p">,</span><span class="w"> </span><span class="n">replacements</span><span class="p">,</span><span class="w"> </span><span class="n">deletions</span><span class="w"></span>
<span class="w">        </span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">expected_diff</span><span class="p">.</span><span class="n">assert_eq</span><span class="p">(</span><span class="o">&amp;</span><span class="n">actual</span><span class="p">);</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">from</span><span class="p">.</span><span class="n">to_owned</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">text_edit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">TextEdit</span>::<span class="n">builder</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="n">diff</span><span class="p">.</span><span class="n">into_text_edit</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">text_edit</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">text_edit</span><span class="p">.</span><span class="n">finish</span><span class="p">().</span><span class="n">apply</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">from</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="o">&amp;*</span><span class="n">from</span><span class="p">,</span><span class="w"> </span><span class="n">to</span><span class="p">,</span><span class="w"> </span><span class="s">"diff did not turn `from` to `to`"</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="214168016"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168016" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168016">(Oct 22 2020 at 10:27)</a>:</h4>
<p>Yeah, that's more readable already</p>



<a name="214168031"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168031" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168031">(Oct 22 2020 at 10:28)</a>:</h4>
<p>We probably can get rid of some internal quotes though</p>



<a name="214168071"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168071" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168071">(Oct 22 2020 at 10:28)</a>:</h4>
<p>(not sure why I put them in my example)</p>



<a name="214168123"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168123" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168123">(Oct 22 2020 at 10:28)</a>:</h4>
<p>Generally, optimize the thing to be as human-readable as possible, and expect would make sure that writing it out is not the pain</p>



<a name="214168177"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168177" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168177">(Oct 22 2020 at 10:29)</a>:</h4>
<p>Well, it would help to print the line number where the op is happening as well. I didn't expect most of the anchors to be whitespace :D</p>



<a name="214168283"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168283" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168283">(Oct 22 2020 at 10:30)</a>:</h4>
<p>Ye a lot of whitespace is being replaced and inserted <span aria-label="big smile" class="emoji emoji-1f604" role="img" title="big smile">:big_smile:</span></p>



<a name="214168357"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168357" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168357">(Oct 22 2020 at 10:31)</a>:</h4>
<p>For whitespace, I think we can special case this and use <code>{:?}</code> of the text of the node</p>



<a name="214168368"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168368" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168368">(Oct 22 2020 at 10:31)</a>:</h4>
<p>so that you get <code>"\n"</code> rather than <code>"
"</code></p>



<a name="214168381"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168381" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168381">(Oct 22 2020 at 10:31)</a>:</h4>
<p>Ye that seems like a good idea</p>



<a name="214168393"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168393" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168393">(Oct 22 2020 at 10:31)</a>:</h4>
<p>regarding line numbers, how would i get those?</p>



<a name="214168473"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168473" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168473">(Oct 22 2020 at 10:32)</a>:</h4>
<p>I am afraind just manually: <code>text[..range.start()].lines().count()</code></p>



<a name="214168499"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214168499" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214168499">(Oct 22 2020 at 10:32)</a>:</h4>
<p>add -/+1 to taste</p>



<a name="214172113"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214172113" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214172113">(Oct 22 2020 at 11:13)</a>:</h4>
<p>Alright, looks good to me I'd say. Question is what makes good tests for this this <span aria-label="sweat smile" class="emoji emoji-1f605" role="img" title="sweat smile">:sweat_smile:</span> </p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">insert_use</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>
<span class="s">use text_edit::TextEdit;</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insertions:</span>

<span class="s">                Line 4: Token(WHITESPACE@56..57 "</span><span class="err">\</span><span class="n">n</span><span class="s">")</span>
<span class="s">                -&gt; use crate::AstNode;</span>
<span class="s">                -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>

<span class="s">                replacements:</span>

<span class="s">                Line 4: Token(IDENT@48..55 "</span><span class="n">AstNode</span><span class="s">") -&gt; TextEdit</span>
<span class="s">                Line 4: Token(WHITESPACE@56..57 "</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>
<span class="s">                Line 2: Token(WHITESPACE@35..37 "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>
<span class="s">                Line 4: Token(CRATE_KW@41..46 "</span><span class="k">crate</span><span class="s">") -&gt; text_edit</span>

<span class="s">                deletions:</span>


<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">remove_use</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>
<span class="s">use text_edit::TextEdit;</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="s">"</span>
<span class="s">use expect_test::{expect, Expect};</span>

<span class="s">use crate::AstNode;</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insertions:</span>



<span class="s">                replacements:</span>

<span class="s">                Line 3: Token(IDENT@51..59 "</span><span class="n">TextEdit</span><span class="s">") -&gt; AstNode</span>
<span class="s">                Line 3: Node(NAME_REF@40..49) -&gt; crate</span>
<span class="s">                Line 2: Token(WHITESPACE@35..36 "</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>
<span class="s">                Line 3: Token(WHITESPACE@60..62 "</span><span class="err">\</span><span class="n">n</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>

<span class="s">                deletions:</span>

<span class="s">                Line 4: use crate::AstNode;</span>
<span class="s">                Line 5: "</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>
<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">merge_use</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="s">"</span>
<span class="s">use std::{</span>
<span class="s">    fmt,</span>
<span class="s">    hash::BuildHasherDefault,</span>
<span class="s">    ops::{self, RangeInclusive},</span>
<span class="s">};</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="s">"</span>
<span class="s">use std::fmt;</span>
<span class="s">use std::hash::BuildHasherDefault;</span>
<span class="s">use std::ops::{self, RangeInclusive};</span>
<span class="s">"</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insertions:</span>

<span class="s">                Line 2: Node(PATH_SEGMENT@5..8)</span>
<span class="s">                -&gt; ::</span>
<span class="s">                -&gt; fmt</span>
<span class="s">                Line 6: Token(WHITESPACE@86..87 "</span><span class="err">\</span><span class="n">n</span><span class="s">")</span>
<span class="s">                -&gt; use std::hash::BuildHasherDefault;</span>
<span class="s">                -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>
<span class="s">                -&gt; use std::ops::{self, RangeInclusive};</span>
<span class="s">                -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>

<span class="s">                replacements:</span>

<span class="s">                Line 2: Token(IDENT@5..8 "</span><span class="n">std</span><span class="s">") -&gt; std</span>

<span class="s">                deletions:</span>

<span class="s">                Line 2: ::</span>
<span class="s">                Line 2: {</span>
<span class="s">                    fmt,</span>
<span class="s">                    hash::BuildHasherDefault,</span>
<span class="s">                    ops::{self, RangeInclusive},</span>
<span class="s">                }</span>
<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[test]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">early_return_assist</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">check_diff</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">fn main() {</span>
<span class="s">    if let Ok(x) = Err(92) {</span>
<span class="s">        foo(x);</span>
<span class="s">    }</span>
<span class="s">}</span>
<span class="s">            "</span><span class="err">#</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">fn main() {</span>
<span class="s">    let x = match Err(92) {</span>
<span class="s">        Ok(it) =&gt; it,</span>
<span class="s">        _ =&gt; return,</span>
<span class="s">    };</span>
<span class="s">    foo(x);</span>
<span class="s">}</span>
<span class="s">            "</span><span class="err">#</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">expect</span><span class="o">!</span><span class="p">[[</span><span class="n">r</span><span class="err">#</span><span class="s">"</span>
<span class="s">                insertions:</span>

<span class="s">                Line 3: Node(BLOCK_EXPR@40..63)</span>
<span class="s">                -&gt; "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                -&gt; match Err(92) {</span>
<span class="s">                        Ok(it) =&gt; it,</span>
<span class="s">                        _ =&gt; return,</span>
<span class="s">                    }</span>
<span class="s">                -&gt; ;</span>
<span class="s">                Line 5: Token(R_CURLY@64..65 "</span><span class="p">}</span><span class="s">")</span>
<span class="s">                -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="s">"</span>
<span class="s">                -&gt; }</span>

<span class="s">                replacements:</span>

<span class="s">                Line 5: Token(R_CURLY@64..65 "</span><span class="p">}</span><span class="s">") -&gt; foo(x);</span>
<span class="s">                Line 3: Token(LET_KW@20..23 "</span><span class="kd">let</span><span class="s">") -&gt; x</span>
<span class="s">                Line 3: Token(IF_KW@17..19 "</span><span class="k">if</span><span class="s">") -&gt; let</span>
<span class="s">                Line 3: Node(BLOCK_EXPR@40..63) -&gt; =</span>
<span class="s">                Line 5: Token(WHITESPACE@63..64 "</span><span class="err">\</span><span class="n">n</span><span class="s">") -&gt; "</span><span class="err">\</span><span class="n">n</span><span class="w">    </span><span class="s">"</span>

<span class="s">                deletions:</span>

<span class="s">                Line 3: "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                Line 3: Ok(x)</span>
<span class="s">                Line 3: "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                Line 3: =</span>
<span class="s">                Line 3: "</span><span class="w"> </span><span class="s">"</span>
<span class="s">                Line 3: Err(92)</span>
<span class="s">            "</span><span class="err">#</span><span class="p">]],</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="214172233"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214172233" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214172233">(Oct 22 2020 at 11:14)</a>:</h4>
<blockquote>
<p>Question is what makes good tests for this this </p>
</blockquote>
<p>Placing <code>mark::hit!</code> into every interesting if and writing minimal suite that hits them all/</p>



<a name="214172319"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214172319" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214172319">(Oct 22 2020 at 11:15)</a>:</h4>
<p>looks nice!</p>



<a name="214176431"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214176431" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214176431">(Oct 22 2020 at 12:02)</a>:</h4>
<p>Alright, pushed the test stuff <span aria-label="thumbs up" class="emoji emoji-1f44d" role="img" title="thumbs up">:thumbs_up:</span></p>



<a name="214176596"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214176596" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214176596">(Oct 22 2020 at 12:04)</a>:</h4>
<p>Interesting, import resolution for the mark macros fails on CI, as well as in RA but not when I build myself</p>



<a name="214176767"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Tree%20diff%20rewrite%20tests/near/214176767" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Wirth <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Tree.20diff.20rewrite.20tests.html#214176767">(Oct 22 2020 at 12:05)</a>:</h4>
<p>Oh I see the problem</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>